package com.xc.filter;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.http.MediaType;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

public class LoginFilter extends UsernamePasswordAuthenticationFilter {

    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {

        // 首先确保进入该过滤器中的请求是POST请求
        if (!request.getMethod().equals("POST")) {
            throw new AuthenticationServiceException(
                    "Authentication method not supported: " + request.getMethod());
        }

        String kaptcha = request.getParameter("kaptcha");

        if(!request.getSession().getAttribute("kaptcha").equals(kaptcha)){
            throw new AuthenticationServiceException("验证码输入错误");
        }


        // 根据请求的content-type来判断参数是JSON格式的还是key/value格式的

        // 如果是JSON格式的，则直接在当前方法中处理；
        if (request.getContentType().equalsIgnoreCase(MediaType.APPLICATION_JSON_VALUE) || request.getContentType().equalsIgnoreCase(MediaType.APPLICATION_JSON_UTF8_VALUE)) {

            Map<String, String> userInfo = new HashMap<>();
            try {
                // 如果请求参数是JSON格式，则首先利用jackson提供的ObjectMapper工具，将输入流转为Map对象
                userInfo = new ObjectMapper().readValue(request.getInputStream(), Map.class);

                // 然后从Map对象中分别提取出用户名／密码信息并构造出Username PasswordAuthenticationToken对象
                String username = userInfo.get(getUsernameParameter());
                String password = userInfo.get(getPasswordParameter());
                UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(
                        username, password);

                setDetails(request, authRequest);

                // 然后调用AuthenticationManager的authenticate方法执行认证操作
                return this.getAuthenticationManager().authenticate(authRequest);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        // 如果是key/value格式的，那直接调用父类的attemptAuthentication方法处理即可。
        return super.attemptAuthentication(request, response);
    }
}
